package wpwork.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import wpwork.base.service.SuperServiceImpl;
import wpwork.base.vo.DownloadVO;
import wpwork.config.ConfigValueUtil;
import wpwork.entity.GpsInfoEntity;
import wpwork.entity.GpsInfoEntity;
import wpwork.entity.WorkPersonJobEntity;
import wpwork.entity.WorkResourcesEntity;
import wpwork.mapper.GpsInfoMapper;
import wpwork.mapper.WorkResourcesMapper;
import wpwork.model.GpsInfoVo;
import wpwork.model.GpsInfoVo2;
import wpwork.model.WorkPersonJobVO;
import wpwork.permission.entity.UserEntity;
import wpwork.permission.mapper.UserMapper;
import wpwork.service.GpsInfoService;
import wpwork.service.WorkResourcesService;
import wpwork.util.DateUtil;
import wpwork.util.ExcelUtil;
import cn.xuyanwu.spring.file.storage.FileInfo;
import wpwork.util.FileUploadUtils;
import wpwork.util.UploaderUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class GpsInfoServiceImpl extends SuperServiceImpl<GpsInfoMapper, GpsInfoEntity> implements GpsInfoService {

    // 在 GpsInfoService 中实现此方法
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private GpsInfoMapper gpsInfoMapper;
    @Autowired
    private ConfigValueUtil configValueUtil;
    @Override
    public List<GpsInfoEntity> queryGpsInfoByConditions(List<String> userId, Long startTime, Long endTime) {
        QueryWrapper<GpsInfoEntity> queryWrapper = new QueryWrapper<>();

        // 用户ID条件
        if (userId != null && !userId.isEmpty()) {
            queryWrapper.in("f_userid", userId);
        }

        // 时间范围条件 - 使用时间戳
        if (startTime != null) {
            queryWrapper.ge("f_time", new Date(startTime));
        }
        if (endTime != null) {
            queryWrapper.le("f_time", new Date(endTime));
        }

        // 添加排序，按时间倒序
        queryWrapper.orderByDesc("f_time");

        return this.list(queryWrapper);
    }

    @Override
    public IPage<GpsInfoVo> fenceQuery(String startTime, String endTime, String name,
                                      String currentPage, String pageSize) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = null;
        Date endDate = null;

        // 创建查询包装器
        LambdaQueryWrapper<GpsInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GpsInfoEntity::getType, 1);

        // 处理时间范围（同前）
        if ("".equals(startTime) && "".equals(endTime)) {
            LocalDate today = LocalDate.now();
            LocalDateTime startOfDay = today.atStartOfDay();
            LocalDateTime endOfDay = today.atTime(23, 59, 59);
            ZoneId zoneId = ZoneId.systemDefault();
            startDate = Date.from(startOfDay.atZone(zoneId).toInstant());
            endDate = Date.from(endOfDay.atZone(zoneId).toInstant());
            queryWrapper.between(GpsInfoEntity::getTime, startDate, endDate);
        } else if (!"".equals(startTime) && "".equals(endTime)) {
            try {
                startDate = sdf.parse(startTime);
                queryWrapper.ge(GpsInfoEntity::getTime, startDate);
            } catch (ParseException e) {
                throw new RuntimeException("开始时间格式错误", e);
            }
        } else if ("".equals(startTime) && !"".equals(endTime)) {
            try {
                endDate = sdf.parse(endTime);
                queryWrapper.le(GpsInfoEntity::getTime, endDate);
            } catch (ParseException e) {
                throw new RuntimeException("结束时间格式错误", e);
            }
        } else if (!"".equals(startTime) && !"".equals(endTime)) {
            try {
                startDate = sdf.parse(startTime);
                endDate = sdf.parse(endTime);
                queryWrapper.between(GpsInfoEntity::getTime, startDate, endDate);
            } catch (ParseException e) {
                throw new RuntimeException("时间格式错误", e);
            }
        }

        // ✅ 新增：如果 name 不为空，关联 user 表进行模糊查询
        if (name != null && !name.trim().isEmpty()) {
            // 方案 A：使用 SQL 子查询（推荐，无需改表结构）
            queryWrapper.inSql(GpsInfoEntity::getRemark2,
                    "SELECT f_id FROM base_user WHERE f_real_name LIKE '%" + name + "%'");
        }

        // 排序
        queryWrapper.orderByDesc(GpsInfoEntity::getTime);

        // 分页处理
        long current = Long.parseLong(currentPage != null && !currentPage.isEmpty() ? currentPage : "1");
        long size = Long.parseLong(pageSize != null && !pageSize.isEmpty() ? pageSize : "10");

        Page<GpsInfoEntity> page = new Page<>(current, size);
        IPage<GpsInfoEntity> resultPage = this.page(page, queryWrapper);

        // 转换为 VO（此时不再过滤！）
        List<GpsInfoVo> voList = entityToVO(resultPage.getRecords());

        // 构造返回的分页对象
        IPage<GpsInfoVo> voIPage = new Page<>();
        voIPage.setTotal(resultPage.getTotal());
        voIPage.setSize(resultPage.getSize());
        voIPage.setCurrent(resultPage.getCurrent());
        voIPage.setRecords(voList);

        return voIPage;
    }

    @Override
    public List<GpsInfoVo> positioningStatistics(String name) {
        List<GpsInfoVo> gpsInfoVos = gpsInfoMapper.positioningStatistics();
        List<GpsInfoVo> gpsInfoVos2 = new ArrayList<>();
        for (GpsInfoVo gpsInfoVo : gpsInfoVos) {
            if(name!=null || "".equals(name)){
                if(gpsInfoVo.getRealName().contains(name)){
                    gpsInfoVos2.add(gpsInfoVo);
                }
            }
        }
        return gpsInfoVos2;
    }

    @Override
    public IPage<GpsInfoVo> getListByPerson(String startTime, String endTime, String name,
                                            String currentPage, String pageSize) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate = null;
        Date endDate = null;

        // 创建查询包装器
        LambdaQueryWrapper<GpsInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GpsInfoEntity::getType, 0);

        // 处理时间范围（同前）
        if ("".equals(startTime) && "".equals(endTime)) {
            LocalDate today = LocalDate.now();
            LocalDateTime startOfDay = today.atStartOfDay();
            LocalDateTime endOfDay = today.atTime(23, 59, 59);
            ZoneId zoneId = ZoneId.systemDefault();
            startDate = Date.from(startOfDay.atZone(zoneId).toInstant());
            endDate = Date.from(endOfDay.atZone(zoneId).toInstant());
            queryWrapper.between(GpsInfoEntity::getTime, startDate, endDate);
        } else if (!"".equals(startTime) && "".equals(endTime)) {
            try {
                startDate = sdf.parse(startTime);
                queryWrapper.ge(GpsInfoEntity::getTime, startDate);
            } catch (ParseException e) {
                throw new RuntimeException("开始时间格式错误", e);
            }
        } else if ("".equals(startTime) && !"".equals(endTime)) {
            try {
                endDate = sdf.parse(endTime);
                queryWrapper.le(GpsInfoEntity::getTime, endDate);
            } catch (ParseException e) {
                throw new RuntimeException("结束时间格式错误", e);
            }
        } else if (!"".equals(startTime) && !"".equals(endTime)) {
            try {
                startDate = sdf.parse(startTime);
                endDate = sdf.parse(endTime);
                queryWrapper.between(GpsInfoEntity::getTime, startDate, endDate);
            } catch (ParseException e) {
                throw new RuntimeException("时间格式错误", e);
            }
        }

        // ✅ 新增：如果 name 不为空，关联 user 表进行模糊查询
        if (name != null && !name.trim().isEmpty()) {
            // 方案 A：使用 SQL 子查询（推荐，无需改表结构）
            queryWrapper.inSql(GpsInfoEntity::getRemark2,
                    "SELECT f_id FROM base_user WHERE f_real_name LIKE '%" + name + "%'");
        }

        // 排序
        queryWrapper.orderByDesc(GpsInfoEntity::getTime);

        // 分页处理
        long current = Long.parseLong(currentPage != null && !currentPage.isEmpty() ? currentPage : "1");
        long size = Long.parseLong(pageSize != null && !pageSize.isEmpty() ? pageSize : "10");

        Page<GpsInfoEntity> page = new Page<>(current, size);
        IPage<GpsInfoEntity> resultPage = this.page(page, queryWrapper);

        // 转换为 VO（此时不再过滤！）
        List<GpsInfoVo> voList = entityToVO(resultPage.getRecords());

        // 构造返回的分页对象
        IPage<GpsInfoVo> voIPage = new Page<>();
        voIPage.setTotal(resultPage.getTotal());
        voIPage.setSize(resultPage.getSize());
        voIPage.setCurrent(resultPage.getCurrent());
        voIPage.setRecords(voList);

        return voIPage;
    }

    @Override
    public List<GpsInfoVo2> getListByGroup(String startTime, String endTime, String name) {

        List<GpsInfoVo2> gpsSummaryByTimeRange = gpsInfoMapper.getGpsSummaryByTimeRange(startTime, endTime);
        return gpsSummaryByTimeRange;
    }
    @Override
    public DownloadVO exportExcelByGroup(String startTime, String endTime) {
        List<GpsInfoVo2> gpsSummaryByTimeRange = gpsInfoMapper.getGpsSummaryByTimeRange(startTime, endTime);
        gpsSummaryByTimeRange.forEach(vo -> {
            if (vo.getTotalDistance() != null) {
                // 如果值接近 0，直接设为 0
                if (vo.getTotalDistance().compareTo(BigDecimal.ZERO) == 0) {
                    vo.setTotalDistance(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
                } else {
                    vo.setTotalDistance(vo.getTotalDistance().setScale(2, RoundingMode.HALF_UP));
                }
            } else {
                vo.setTotalDistance(BigDecimal.ZERO);
            }
        });
        // 2. 构建 Excel 列定义
        List<ExcelExportEntity> entityList = buildGpsExportEntitiesByGroup();

        // 3. 调用通用导出方法
        return exportExcelToDownloadVO(
                gpsSummaryByTimeRange,                    // 数据
                entityList,                 // 列配置
                "GPS信息记录",               // Sheet 名称
                "群组GPS信息导出_"                  // 文件名前缀
        );
    }


    public List<GpsInfoVo> entityToVO(List<GpsInfoEntity> gpsInfoEntities) {
        List<GpsInfoVo> gpsInfoVos = new ArrayList<>();

        for (GpsInfoEntity gpsInfo : gpsInfoEntities) {
            GpsInfoVo gpsInfoVo = new GpsInfoVo();

            // 根据 remark2（用户ID）查询用户真实姓名
            UserEntity userEntity = userMapper.selectById(gpsInfo.getRemark2());
            if (userEntity == null) {
                continue; // 用户不存在则跳过
            }

            // 设置 VO 字段
            gpsInfoVo.setUserid(gpsInfo.getUserid());
            gpsInfoVo.setRealName(userEntity.getRealName());
            gpsInfoVo.setType(gpsInfo.getType());
            gpsInfoVo.setLng(gpsInfo.getLng());
            gpsInfoVo.setLat(gpsInfo.getLat());
            gpsInfoVo.setDistance(gpsInfo.getDistance());
            gpsInfoVo.setRemark(gpsInfo.getRemark());
            gpsInfoVo.setRemark1(gpsInfo.getRemark1());
            gpsInfoVo.setRemark2(gpsInfo.getRemark2());
            gpsInfoVo.setTime(gpsInfo.getTime());
            gpsInfoVo.setTenantId(gpsInfo.getTenantId());

            gpsInfoVos.add(gpsInfoVo);
        }
        return gpsInfoVos;
    }

    public List<GpsInfoVo> entityToVO(List<GpsInfoEntity> gpsInfoEntities, String name) {
        List<GpsInfoVo> gpsInfoVos = new ArrayList<>();
        for (GpsInfoEntity gpsInfo : gpsInfoEntities) {
            GpsInfoVo gpsInfoVo = new GpsInfoVo();
            UserEntity userEntity = userMapper.selectById(gpsInfo.getRemark2());
            if(name!=null && !"".equals(name)){
                if(!userEntity.getRealName().contains(name)){
                    continue;
                }
            }
            gpsInfoVo.setUserid(gpsInfo.getUserid());
            gpsInfoVo.setRealName(userEntity.getRealName());
            gpsInfoVo.setType(gpsInfo.getType());
            gpsInfoVo.setLng(gpsInfo.getLng());
            gpsInfoVo.setLat(gpsInfo.getLat());
            gpsInfoVo.setDistance(gpsInfo.getDistance());
            gpsInfoVo.setRemark(gpsInfo.getRemark());
            gpsInfoVo.setRemark1(gpsInfo.getRemark1());
            gpsInfoVo.setRemark2(gpsInfo.getRemark2());
            gpsInfoVo.setTime(gpsInfo.getTime());
            gpsInfoVo.setTenantId(gpsInfo.getTenantId());
            gpsInfoVos.add(gpsInfoVo);
        }
        return gpsInfoVos;
    }

    @Override
    public DownloadVO exportExcelByPerson(String startTime, String endTime, String name) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startDate;
        Date endDate;
        LambdaQueryWrapper<GpsInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GpsInfoEntity::getType, 0);
        if (!"".equals(startTime) && "".equals(endTime)){
            try {
                startDate = sdf.parse(startTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            queryWrapper.and(wrapper ->
                    wrapper.ge(GpsInfoEntity::getTime, startDate)
            );
        } else if ( "".equals(startTime) && !"".equals(endTime)) {
            try {
                endDate = sdf.parse(endTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            queryWrapper.and(wrapper ->
                    wrapper.le(GpsInfoEntity::getTime, endDate)
            );
        } else if ( !"".equals(startTime) && !"".equals(endTime)) {
            try {
                startDate = sdf.parse(startTime);
                endDate = sdf.parse(endTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            queryWrapper.and(wrapper ->
                    wrapper.ge(GpsInfoEntity::getTime, startDate)
            ).and(wrapper ->
                    wrapper.le(GpsInfoEntity::getTime, endDate)
            );
        }
        queryWrapper.orderByDesc(GpsInfoEntity::getUserid);
        queryWrapper.orderByDesc(GpsInfoEntity::getTime);
        List<GpsInfoEntity> gpsInfoEntities = this.list(queryWrapper);
        List<GpsInfoVo> workPersonJobVOS = entityToVO(gpsInfoEntities,name);

        // 2. 构建 Excel 列定义
        List<ExcelExportEntity> entityList = buildGpsExportEntities();

        workPersonJobVOS.forEach(vo -> {
            if (vo.getDistance() != null) {
                // 如果值接近 0，直接设为 0
                if (vo.getDistance().compareTo(BigDecimal.ZERO) == 0) {
                    vo.setDistance(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
                } else {
                    vo.setDistance(vo.getDistance().setScale(2, RoundingMode.HALF_UP));
                }
            } else {
                vo.setDistance(BigDecimal.ZERO);
            }
        });

        // 3. 调用通用导出方法
        return exportExcelToDownloadVO(
                workPersonJobVOS,                    // 数据
                entityList,                 // 列配置
                "GPS轨迹记录",               // Sheet 名称
                "人员GPS信息导出_"                  // 文件名前缀
        );
    }


    /**
     * 通用 Excel 导出工具方法
     *
     * @param dataList       数据列表（POJO 列表）
     * @param entityList     Excel 列定义（ExcelExportEntity 列表）
     * @param sheetName      sheet 名称
     * @param fileNamePrefix 文件名前缀
     * @return DownloadVO 包含文件名和下载 URL
     */
    public DownloadVO exportExcelToDownloadVO(
            List<?> dataList,
            List<ExcelExportEntity> entityList,
            String sheetName,
            String fileNamePrefix
    ) {
        DownloadVO vo = DownloadVO.builder().build();
        try {
            ExportParams exportParams = new ExportParams(null, sheetName);
            exportParams.setType(ExcelType.XSSF);

            Workbook workbook;
            if (entityList != null && !entityList.isEmpty() && dataList != null && !dataList.isEmpty()) {
                workbook = ExcelExportUtil.exportExcel(exportParams, entityList, dataList);
            } else {
                // 防止空数据报错，创建空表
                workbook = new XSSFWorkbook();
                workbook.createSheet(sheetName);
            }

            String fileName = fileNamePrefix + DateUtil.dateFormatByPattern(new Date(), "yyyyMMddHHmmss") + ".xlsx";
            MultipartFile multipartFile = ExcelUtil.workbookToCommonsMultipartFile(workbook, fileName);

            String temporaryFilePath = configValueUtil.getTemporaryFilePath();
            FileInfo fileInfo = FileUploadUtils.uploadFile(multipartFile, temporaryFilePath, fileName);

            vo.setName(fileInfo.getFilename());
            vo.setUrl(UploaderUtil.uploaderFile(fileInfo.getFilename() + "#" + "Temporary") + "&name=" + fileName);

        } catch (Exception e) {
            log.error("导出Excel并生成DownloadVO失败: " + e.getMessage(), e);
        }
        return vo;
    }

    private List<ExcelExportEntity> buildGpsExportEntities() {
        List<ExcelExportEntity> entityList = new ArrayList<>();

//        entityList.add(new ExcelExportEntity("用户编号", "userid"));
        entityList.add(new ExcelExportEntity("姓名", "realName",20));
//        entityList.add(new ExcelExportEntity("类型", "type",20));

        // 经纬度
        entityList.add(new ExcelExportEntity("经度", "lng",20));
        entityList.add(new ExcelExportEntity("纬度", "lat",20));

        // 距离（假设单位是公里，保留2位小数）
        ExcelExportEntity distanceEntity = new ExcelExportEntity("距离", "distance",20);
        distanceEntity.setFormat("0.00"); // 格式化 BigDecimal
        entityList.add(distanceEntity);

        // 备注类字段（可选显示）
//        entityList.add(new ExcelExportEntity("地点", "remark"));
        entityList.add(new ExcelExportEntity("地点", "remark1",20));
//        entityList.add(new ExcelExportEntity("备注2", "remark2"));

        // 时间格式化
        ExcelExportEntity timeEntity = new ExcelExportEntity("上传时间", "time",20);
        timeEntity.setFormat("yyyy-MM-dd HH:mm:ss"); // 时间格式
        entityList.add(timeEntity);

        // 租户ID（调试用，可隐藏）
        // entityList.add(new ExcelExportEntity("租户ID", "tenantId"));

        return entityList;
    }

    private List<ExcelExportEntity> buildGpsExportEntitiesByGroup() {
        List<ExcelExportEntity> entityList = new ArrayList<>();
        entityList.add(new ExcelExportEntity("群组名", "groupname",20));
        entityList.add(new ExcelExportEntity("人员名称", "realName",20));
        ExcelExportEntity distanceEntity = new ExcelExportEntity("距离", "totalDistance",20);
        distanceEntity.setFormat("0.00"); // 格式化 BigDecimal
        entityList.add(distanceEntity);
        return entityList;
    }

    @Override
    public IPage<GpsInfoVo> getListWithJoinTable(String startTime, String endTime, String name,
                                                 String currentPage, String pageSize) {

        // 处理分页参数
        long current = Long.parseLong(currentPage != null && !currentPage.isEmpty() ? currentPage : "1");
        long size = Long.parseLong(pageSize != null && !pageSize.isEmpty() ? pageSize : "10");

        Page<GpsInfoVo> page = new Page<>(current, size);

        // 调用Mapper中的自定义SQL方法（需要在Mapper XML中定义）
        IPage<GpsInfoVo> resultPage = gpsInfoMapper.getListWithJoinTable(page, startTime, endTime, name);

        return resultPage;
    }



}
